/*
 * @Version: 0.0.1
 * @Author: ider
 * @Date: 2021-05-14 18:50:48
 * @LastEditors: ider
 * @LastEditTime: 2021-05-21 15:37:02
 * @Description: 更新 article file 到文件,版本控制，Redirect 不保存 Revision 了
 */

package main

import (
	"compress/bzip2"
	"encoding/xml"
	"historyOfWikipedia/internal/config"
	"historyOfWikipedia/internal/database/mongodb"
	"historyOfWikipedia/internal/model"
	"io"
	"os"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	log "github.com/sirupsen/logrus"
)

type redirect struct {
	Title string `xml:"title,attr"`
}

type Page struct {
	ID                int64    `xml:"id"`
	Ns                int32    `xml:"ns"`
	Title             string   `xml:"title"`
	Redirect          redirect `xml:"redirect"`
	RevisionText      string   `xml:"revision>text"`
	RevisionID        int64    `xml:"revision>id"`
	RevisionParentid  int64    `xml:"revision>parentid"`
	RevisionTimestamp string   `xml:"revision>timestamp"`
	RevisionComment   string   `xml:"revision>comment"`
	RevisionUser      string   `xml:"revision>contributor>username"`
}

func main() {
	// 先处理文件名
	log.Println(config.Env.ArticleXmlFilePath)
	// 找出时间参数
	article_version, err := strconv.Atoi(strings.Split(config.Env.ArticleXmlFilePath, "-")[1])
	if err != nil {
		log.Fatal("文件选择错误")
	}
	log.Println(article_version)

	var revision_update_count int64
	pageChan := make(chan Page, 1000)
	// 多开处理进程
	threadCount := 20
	wg := sync.WaitGroup{}
	wg.Add(threadCount)
	for i := 0; i < threadCount; i++ {
		go func() {
			mongoObj := mongodb.NewMongoClient(config.Env.MongoUri)
			for page := range pageChan {
				pao := model.PagesArticlesObj{
					ID:         page.ID,
					Version:    int64(article_version),
					Ns:         page.Ns,
					Redirect:   page.Redirect.Title,
					Title:      page.Title,
					RevisionID: page.RevisionID,
				}
				mongoObj.Update_Pages_Articles(&pao)

				// 重定向的不保存 版本信息
				if pao.Redirect == "" {
					continue
				}

				timestamp, err := time.Parse("2006-01-02T15:04:05Z", page.RevisionTimestamp)
				if err == nil {
					// revObjectID := primitive.NewObjectID()
					rio := model.RevisionInfoObj{
						// ID:        revObjectID,
						Revid:     page.RevisionID,
						ArticleID: page.ID,
						Comment:   page.RevisionComment,
						ParentID:  page.RevisionParentid,
						User:      page.RevisionUser,
						Timestamp: timestamp,
					}
					status, revisionObjectID, err := mongoObj.Update_Revision_Info(&rio)
					if status {
						atomic.AddInt64(&revision_update_count, 1)
					}

					if err == nil {
						rdo := model.RevisionDetailObj{
							ID:        revisionObjectID,
							Revid:     page.RevisionID,
							ArticleID: page.ID,
							Timestamp: timestamp,
							Text:      page.RevisionText,
						}
						mongoObj.Update_Revision_Detail(&rdo, revisionObjectID)
					}
				} else {
					log.Println("时间格式化失败，跳过该条记录", page.RevisionTimestamp)
				}
			}
			wg.Done()
		}()
	}
	fi, err := os.Open(config.Env.ArticleXmlFilePath)
	if err != nil {
		log.Fatal("读取文件错误:", err)
	}
	defer fi.Close()

	fz := bzip2.NewReader(fi)

	d := xml.NewDecoder(fz)
	count := 0
	for {
		t, tokenErr := d.Token()
		if tokenErr != nil {
			if tokenErr == io.EOF {
				break
			}
			// handle error
		}
		switch t := t.(type) {
		case xml.StartElement:
			if t.Name.Local == "page" {
				var page Page
				if err := d.DecodeElement(&page, &t); err != nil {
					log.Warning(err)
				}
				pageChan <- page
				if count%10000 == 0 {
					log.Info(count)
				}
				count++
			}
		}
	}
	close(pageChan)
	wg.Wait()
	log.Info("更新了 reversion count:", revision_update_count)
	log.Info("over ", count)
}
